home *** CD-ROM | disk | FTP | other *** search
/ Programming an RTS Game with Direct3D / Programming an RTS Game with Direct3D.iso / Examples / Chapter 14 / Example 14.1 / StrategyMap.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2006-06-30  |  6.2 KB  |  251 lines

  1. #include "strategyMap.h"
  2.  
  3. //////////////////////////////////////////////////////////////////////////////////////////
  4. //                            AREA                                                        //
  5. //////////////////////////////////////////////////////////////////////////////////////////
  6.  
  7. AREA::AREA(RECT mArea)
  8. {
  9.     m_mapArea = mArea;
  10.     m_status = STATUS_UNKNOWN;
  11.     m_enemyPresence = 0;
  12.     m_friendlyPresence = 0;
  13.     m_value = 0;
  14. }
  15.  
  16. void AREA::Update(TERRAIN *terrain, int teamNo)
  17. {
  18.     m_enemyPresence = 0;
  19.     m_friendlyPresence = 0;
  20.     m_value = 0;
  21.     bool visible = false;
  22.  
  23.     if(terrain == NULL)
  24.         return;
  25.  
  26.     try
  27.     {
  28.         //Calculate presence in this area
  29.         for(int y=m_mapArea.top;y<m_mapArea.bottom;y++)
  30.             for(int x=m_mapArea.left;x<m_mapArea.right;x++)        
  31.             {
  32.                 MAPTILE *tile = terrain->GetTile(x, y);
  33.  
  34.                 if(tile != NULL && tile->m_pMapObject != NULL)
  35.                 {
  36.                     if(tile->m_pMapObject->m_team == teamNo)
  37.                     {
  38.                         m_friendlyPresence += tile->m_pMapObject->m_hp * tile->m_pMapObject->m_damage;
  39.                         visible = true;
  40.                     }
  41.                     else m_enemyPresence += tile->m_pMapObject->m_hp * tile->m_pMapObject->m_damage;
  42.                 }
  43.             }
  44.  
  45.         //Set area status
  46.         if(visible)
  47.         {
  48.             if(m_enemyPresence > 0 && m_friendlyPresence > 0)m_status = STATUS_CONFLICT;
  49.             else if(m_friendlyPresence > 0)m_status = STATUS_FRIENDLY;
  50.             else if(m_enemyPresence > 0)m_status = STATUS_ENEMY;
  51.         }
  52.     }
  53.     catch(...)
  54.     {
  55.         debug.Print("Error in AREA::Update()");
  56.     }
  57. }
  58.  
  59. bool AREA::Connected(TERRAIN *terrain, INTPOINT from)
  60. {
  61.     if(terrain == NULL)return false;
  62.  
  63.     try
  64.     {
  65.         MAPTILE *tile = terrain->GetTile(from);
  66.         if(tile == NULL)return false;
  67.  
  68.         for(int y=m_mapArea.top;y<m_mapArea.bottom;y++)
  69.             for(int x=m_mapArea.left;x<m_mapArea.right;x++)
  70.             {
  71.                 MAPTILE *t = terrain->GetTile(x, y);
  72.                 if(t != NULL && t->m_set == tile->m_set)
  73.                     return true;
  74.             }
  75.     }
  76.     catch(...)
  77.     {
  78.         debug.Print("Error in AREA::Connected()");
  79.     }
  80.  
  81.     return false;
  82. }
  83.  
  84. INTPOINT AREA::GetCenter()
  85. {
  86.     return INTPOINT(m_mapArea.left + (m_mapArea.right - m_mapArea.left) * 0.5f,
  87.                     m_mapArea.top + (m_mapArea.bottom - m_mapArea.top) * 0.5f);
  88. }
  89.  
  90. //////////////////////////////////////////////////////////////////////////////////////////
  91. //                            INFLUENCE MAP                                                //
  92. //////////////////////////////////////////////////////////////////////////////////////////
  93.  
  94. STRATEGY_MAP::STRATEGY_MAP(TERRAIN *_terrain, PLAYER *_player, INTPOINT numAreas)
  95. {
  96.     m_pTerrain = _terrain;
  97.     m_pPlayer = _player;
  98.  
  99.     if(m_pTerrain == NULL || m_pPlayer == NULL)return;
  100.  
  101.     m_size = m_pTerrain->m_size;
  102.  
  103.     //Create influence map
  104.     m_pInfluenceMap = new int[m_size.x * m_size.y];
  105.     memset(m_pInfluenceMap, 0, sizeof(int) * m_size.x * m_size.y);
  106.  
  107.     //Create sub areas
  108.     for(int y=0;y<numAreas.y;y++)
  109.         for(int x=0;x<numAreas.x;x++)
  110.         {
  111.             RECT r = {x * (m_size.x - 1) / (float)numAreas.x, 
  112.                       y * (m_size.y - 1) / (float)numAreas.y, 
  113.                     (x+1) * (m_size.x - 1) / (float)numAreas.x,
  114.                     (y+1) * (m_size.y - 1) / (float)numAreas.y};
  115.     
  116.             m_areas.push_back(AREA(r));
  117.         }
  118. }
  119.  
  120. STRATEGY_MAP::~STRATEGY_MAP()
  121. {
  122.     if(m_pInfluenceMap != NULL)
  123.         delete [] m_pInfluenceMap;
  124.     m_pInfluenceMap = NULL;
  125. }
  126.  
  127. void STRATEGY_MAP::Update(std::set<MAPOBJECT*> &enemies)
  128. {
  129.     if(m_pTerrain == NULL || m_pPlayer ==  NULL)return;
  130.  
  131.     try
  132.     {
  133.         //Reset influence map
  134.         memset(m_pInfluenceMap, 0, sizeof(int) * m_size.x * m_size.y);
  135.  
  136.         //Add positive influence from friendly units
  137.         for(int m=0;m<m_pPlayer->m_mapObjects.size();m++)
  138.             if(m_pPlayer->m_mapObjects[m] != NULL && !m_pPlayer->m_mapObjects[m]->m_dead)
  139.             {
  140.                 MAPOBJECT *mo = m_pPlayer->m_mapObjects[m];
  141.                 RECT r = mo->GetMapRect(mo->m_sightRadius);
  142.  
  143.                 if(mo->m_pTerrain != NULL && mo->m_pTerrain->Within(mo->m_mappos))
  144.                     for(int y=r.top;y<=r.bottom;y++)
  145.                         for(int x=r.left;x<=r.right;x++)
  146.                         {
  147.                             INTPOINT p(x, y);
  148.  
  149.                             if(m_pTerrain->Within(p))
  150.                             {    
  151.                                 float multiplier = (mo->m_sightRadius - mo->m_mappos.Distance(p)) / mo->m_sightRadius;
  152.                                 if(multiplier < 0.0f)multiplier = 0.0f;
  153.                                 m_pInfluenceMap[y * m_size.x + x] += mo->m_hp * mo->m_damage * multiplier;
  154.                             }
  155.                         }
  156.             }
  157.  
  158.         //Subtract negative influence from enemy units
  159.         std::set<MAPOBJECT*>::iterator i;
  160.         for(i=enemies.begin();i != enemies.end();i++)
  161.         {
  162.             if((*i) != NULL && !(*i)->m_dead)
  163.             {
  164.                 MAPOBJECT *mo = (*i);
  165.                 RECT r = mo->GetMapRect(mo->m_sightRadius);
  166.  
  167.                 if(mo->m_pTerrain != NULL && mo->m_pTerrain->Within(mo->m_mappos))
  168.                     for(int y=r.top;y<=r.bottom;y++)
  169.                         for(int x=r.left;x<=r.right;x++)
  170.                         {
  171.                             INTPOINT p(x, y);
  172.  
  173.                             if(m_pTerrain->Within(p))
  174.                             {    
  175.                                 float multiplier = (mo->m_sightRadius - mo->m_mappos.Distance(p)) / mo->m_sightRadius;
  176.                                 if(multiplier < 0.0f)multiplier = 0.0f;
  177.                                 m_pInfluenceMap[y * m_size.x + x] -= mo->m_hp * mo->m_damage * multiplier;
  178.                             }
  179.                         }
  180.             }
  181.         }
  182.  
  183.         //Update Map Areas
  184.         for(int i=0;i<m_areas.size();i++)
  185.             m_areas[i].Update(m_pTerrain, m_pPlayer->m_teamNo);
  186.     }
  187.     catch(...)
  188.     {
  189.         debug.Print("Error in STRATEGY_MAP::Update()");
  190.     }
  191. }
  192.  
  193.  
  194. AREA* STRATEGY_MAP::GetScoutArea(INTPOINT from)
  195. {
  196.     int index = -1;
  197.     float distance = 100000.0f;
  198.  
  199.     //Find closest unexplored area
  200.     for(int i=0;i<m_areas.size();i++)
  201.     {
  202.         INTPOINT areaCenter = m_areas[i].GetCenter();
  203.  
  204.         if(m_areas[i].m_status == STATUS_UNKNOWN && m_areas[i].Connected(m_pTerrain, from))
  205.         {
  206.             float d = from.Distance(areaCenter) + m_pPlayer->m_teamStartLocation.Distance(areaCenter) * 0.6f;
  207.  
  208.             if(d < distance)
  209.             {
  210.                 index = i;
  211.                 distance = d;
  212.             }
  213.         }
  214.     }
  215.  
  216.     if(index >= 0)
  217.         return &m_areas[index];
  218.     else return GetRandomArea();
  219. }
  220.  
  221. AREA* STRATEGY_MAP::GetAttackArea(INTPOINT from)
  222. {
  223.     int index = -1;
  224.     float distance = 100000.0f;
  225.  
  226.     //Find closest enemy occupied area
  227.     for(int i=0;i<m_areas.size();i++)
  228.     {
  229.         INTPOINT areaCenter = m_areas[i].GetCenter();
  230.  
  231.         if(m_areas[i].m_status == STATUS_ENEMY || m_areas[i].m_status == STATUS_CONFLICT)
  232.         {
  233.             float d = from.Distance(areaCenter) + m_pPlayer->m_teamStartLocation.Distance(areaCenter) * 0.6f;
  234.  
  235.             if(d < distance)
  236.             {
  237.                 index = i;
  238.                 distance = d;
  239.             }
  240.         }
  241.     }
  242.  
  243.     if(index >= 0)
  244.         return &m_areas[index];
  245.     else return GetRandomArea();
  246. }
  247.  
  248. AREA* STRATEGY_MAP::GetRandomArea()
  249. {
  250.     return &m_areas[rand()%m_areas.size()];
  251. }